﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Office
{

    /// <summary>
    /// excel 单元格坐标快速计算
    /// </summary>
    public class ExcelRPosition
    {

        /// <summary>
        /// 26进制转化
        /// </summary>
        protected static char[] x26 = new char[] {
            'A','B','C','D','E','F','G',
            'H','I','J','K','L','M','N',
            'O','P','Q',
            'R','S','T',
            'U','V','W',
            'X','Y','Z'};

        /// <summary>
        /// 当前行号
        /// </summary>
        protected long _currentIndex = 1L;


        /// <summary>
        /// 当前列号的值
        /// </summary>
        protected long _currentColumn = 1L;


        /// <summary>
        /// 获得或者设置当前行号
        /// </summary>
        public long CurrentIndex
        {
            get
            {
                return _currentIndex;
            }
            set
            {
                _currentIndex = (value <= 0 ? 1 : value);
            }
        }


        /// <summary>
        /// 获得或者设置当前列号
        /// </summary>
        public string CurrentColumn
        {
            get
            {
                return GetColumn(_currentColumn);
            }
            set
            {
                _currentColumn = SetColumn(value);
            }
        }

        /// <summary>
        /// 获得当前坐标
        /// </summary>

        public string GetCurrentPosition
        {
            get
            {
                return GetColumn(_currentColumn) + _currentIndex.ToString();
            }
        }


        /// <summary>
        /// 下N行的坐标（行号加next）
        /// </summary>
        /// <param name="next">往下多少行?,默认往下1行</param>
        /// <returns></returns>
        public ExcelRPosition NextRaws(long next=1)
        {
            if (_currentIndex + next <= 0)
            {
                _currentIndex = 1;
            }
            else
            {
                _currentIndex = _currentIndex + next;
            }
            return this;
        }


        /// <summary>
        /// 上N行的坐标（行号减去next）
        /// </summary>
        /// <param name="next">往上多少行?,默认往上1行</param>
        /// <returns></returns>
        public ExcelRPosition PreviousRaws(long previous = 1)
        {
            if (_currentIndex - previous <= 0)
            {
                _currentIndex = 1;
            }
            else
            {
                _currentIndex = _currentIndex - previous;
            }
            return this;
        }


        /// <summary>
        /// 后N列的坐标（列号加next）
        /// </summary>
        /// <param name="next">往后多少行?,默认往后1行</param>
        /// <returns></returns>
        public ExcelRPosition NextCloumns(long next = 1)
        {
            
            if (_currentColumn + next <= 0)
            {
                _currentColumn = 1;
            }
            else
            {
                _currentColumn = _currentColumn + next;
            }
            return this;
        }


        /// <summary>
        /// 上N行的坐标（行号减去next）
        /// </summary>
        /// <param name="next">往上多少行?,默认往上1行</param>
        /// <returns></returns>
        public ExcelRPosition PreviousColumn(long previous = 1)
        {
            if (_currentColumn - previous <= 0)
            {
                _currentColumn = 1;
            }
            else
            {
                _currentColumn = _currentColumn - previous;
            }
            return this;
        }



        /// <summary>
        /// 往下另起N行的坐标（行号加next,列号为1）
        /// </summary>
        /// <param name="next">往下多少行?,默认往下1行</param>
        /// <returns></returns>
        public ExcelRPosition OtherNextRaws(long next = 1)
        {
            if (_currentIndex + next <= 0)
            {
                _currentIndex = 1;
            }
            else
            {
                _currentIndex = _currentIndex + next;
            }

            _currentColumn = 1;
            return this;
        }


        /// <summary>
        /// 往上另起N行的坐标（行号减去next,列号为1）
        /// </summary>
        /// <param name="next">往上多少行?,默认往上1行</param>
        /// <returns></returns>
        public ExcelRPosition OtherPreviousRaws(long previous = 1)
        {
            if (_currentIndex - previous <= 0)
            {
                _currentIndex = 1;
            }
            else
            {
                _currentIndex = _currentIndex - previous;
            }

            _currentColumn = 1;
            return this;
        }


        /// <summary>
        /// 往后另起N列的坐标（列号加next,行号为1）
        /// </summary>
        /// <param name="next">往后多少行?,默认往后1行</param>
        /// <returns></returns>
        public ExcelRPosition OtherNextCloumns(long next = 1)
        {

            if (_currentColumn + next <= 0)
            {
                _currentColumn = 1;
            }
            else
            {
                _currentColumn = _currentColumn + next;
            }

            _currentIndex = 1;
            return this;
        }


        /// <summary>
        /// 往上另起N行的坐标（行号减去next）
        /// </summary>
        /// <param name="previous">往上多少行?,默认往上1行</param>
        /// <returns></returns>
        public ExcelRPosition OtherPreviousColumn(long previous = 1)
        {
            if (_currentColumn - previous <= 0)
            {
                _currentColumn = 1;
            }
            else
            {
                _currentColumn = _currentColumn - previous;
            }

            _currentIndex = 1;
            return this;
        }




        #region 列号相互转换



        protected string GetColumn(long column)
        {
            if ((column - 1) / 26 == 0)
            {
                return x26[(column - 1) % 26].ToString();
            }
            else
            {
                return GetColumn(column / 26)+x26[(column % 26 - 1)].ToString();
            }

        }


        protected long SetColumn(string column)
        {
            column = column.ToUpper();

            if (string.IsNullOrEmpty(column)||Regex.IsMatch(column, "[^A-Z]+"))
            {
                throw new Exception("参数错误");
            }

            int i = 1;
            long count = 0;
            foreach(var c in column.ToCharArray())
            {
                count += (c - 'A' + 1) *(long)Math.Pow(26,column.Length-i);
                i++;
            }

            return count;

        }

        #endregion

    }
}
